package com.apache.gateway.config;

import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.HttpCookie;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.nio.CharBuffer;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;

/**
 * @description:
 * @author: Hou Dayu
 * @date: Created in 2021/2/2
 */
public class GatewayServerHttpRequest extends ServerHttpRequestDecorator {

    private boolean bufferCached = false;
    private Mono<Void> progress = null;
    private final List<DataBuffer> dataBuffers = new ArrayList<>();
    private HttpHeaders headers = new HttpHeaders();
    MultiValueMap<String, HttpCookie> cookieMultiValueMap = new LinkedMultiValueMap();
    public GatewayServerHttpRequest(ServerHttpRequest delegate) {
        super(delegate);
        headers.putAll(super.getHeaders());
        cookieMultiValueMap.putAll(super.getCookies());
        String scheme = delegate.getURI().getScheme();
        String serverName = delegate.getURI().getHost();
        String severPort = "";
        if(80 !=delegate.getURI().getPort()){
            severPort =  ":" + delegate.getURI().getPort();
        }
        headers.add("realServerName",scheme + "://" + serverName + severPort);
    }

    public void setHeaders(String key ,String value) {
        headers.add(key,value);
    }

    public String getHeader(String headerName){
       return headers.getFirst(headerName);
    }

    public HttpHeaders getHeaders(){
        return headers;
    }

    public String getCookies(String key) {
        HttpCookie cookie = cookieMultiValueMap.getFirst(key);
        if(cookie == null){
            return "";
        }
        return cookie.getValue();
    }

    public void setCookies(String key ,String value) {
        HttpCookie cookie = new HttpCookie(key,value);
        cookieMultiValueMap.add(key,cookie);
    }

    public void delCookieAll(){
        cookieMultiValueMap.clear();
    }

    /*public Flux<DataBuffer> getBody() {
        synchronized (dataBuffers) {
            if (bufferCached) {
                return copy();
            }
            if (progress == null) {
                progress = cache();
            }
            return progress.thenMany(Flux.defer(this::copy));
        }
    }*/

    /**
     * 请求body参数内容
     */
    /*public AtomicReference<String> getRequestBody(){
        Flux<DataBuffer> body = getBody();
        AtomicReference<String> requestBody = new AtomicReference<>("");
        body.subscribe(buffer -> { //读取requestBody传参
            CharBuffer charBuffer = StandardCharsets.UTF_8.decode(buffer.asByteBuffer());
            requestBody.set(charBuffer.toString());
            DataBufferUtils.release(buffer);
        });
        return requestBody;
    }*/


    private Flux<DataBuffer> copy() {
        return Flux.fromIterable(dataBuffers).map(buf -> buf.factory().wrap(buf.asByteBuffer()));
    }

    private Mono<Void> cache() {
        return super.getBody()
                .map(dataBuffers::add)
                .then(Mono.defer(()-> {
                    bufferCached = true;
                    progress = null;
                    return Mono.empty();
                }));
    }
}
